package fwfxserver

import (
	"context"
	grpc2 "gitee.com/zxs-micro/zxs-micro-common/grpc"
	"gitee.com/zxs-micro/zxs-micro-common/grpc/clients"
	"gitee.com/zxs-micro/zxs-micro-fuwufaxian/grpc/protos/fwfx"
	"github.com/pkg/errors"
	"google.golang.org/grpc"
	"google.golang.org/grpc/connectivity"
	"sync"
)

type CommonFuwufaxinClient struct {
	c fwfx.FuwufaxiansClient
	clients.CommonClients
}

var cs = make(map[string]*CommonFuwufaxinClient)
var clock sync.Mutex

func GenerateFwfxClients(addr string) (*CommonFuwufaxinClient, error) {
	var err error
	clock.Lock()
	cli, ok := cs[addr]
	clock.Unlock()
	if !ok {
		cli = new(CommonFuwufaxinClient)
		cli.ClientConn, err = grpc.Dial(addr, grpc2.GetClientDialOpts()...)
		if err != nil {
			return nil, err
		}
		cli.c = fwfx.NewFuwufaxiansClient(cli.ClientConn)
		cli.RemoteAddr = addr
		clock.Lock()
		cs[addr] = cli
		clock.Unlock()
	}
	return cli, nil
}

func (f *CommonFuwufaxinClient) InjectNewServer(localAddr, localCert, servType string) (string, error) {
	c := f.c
	var fx fwfx.FuwufaxianPb
	fx.RemoteAddr = localAddr + "/" + servType
	fx.RemoteCert = localCert
	resp, err := c.Fxfw(context.Background(), &fx)
	if err == nil && resp.IsSuccess {
		return resp.SelfId, nil
	} else if err != nil {
		return "", errors.Wrap(err, "服务注册失败！")
	}

	return "", errors.New("服务注册失败！")
}

func (f *CommonFuwufaxinClient) GetExistServer(serverType string) ([]byte, error) {
	err := f.CheckConn()
	if err != nil {
		return nil, err
	}
	c := f.c
	resp, err := c.FuwuList(context.Background(), &fwfx.ListRequest{
		QueryTypes: serverType,
	})
	if err != nil {
		return nil, err
	}
	return resp.ListBytes, nil
}

func (f *CommonFuwufaxinClient) ExecBusiness(params [][]byte, token, url string) ([]byte, error) {
	err := f.CheckConn()
	if err != nil {
		return nil, err
	}
	c := f.c
	result, err := c.Exec(context.Background(), &fwfx.ExecRequest{
		Params:  params,
		Token:   token,
		ExecUrl: url,
	})
	if err != nil {
		return nil, err
	}
	return result.Payload, err
}

func (c *CommonFuwufaxinClient) CheckConn() (err error) {
	c.ClientLock.Lock()
	if c.ClientConn.GetState() == connectivity.Shutdown {
		c.ClientConn, err = grpc.Dial(c.RemoteAddr, grpc2.GetClientDialOpts()...)
		c.c = fwfx.NewFuwufaxiansClient(c.ClientConn)
	}
	c.ClientLock.Unlock()
	return
}

func (c *CommonFuwufaxinClient) ShutdownClient() {
	c.ClientLock.Lock()
	c.ClientConn.Close()
	c.ClientLock.Unlock()
	clock.Lock()
	delete(cs, c.RemoteAddr)
	clock.Unlock()
}
